﻿

#include "HelloWorldScene.h"


int data[13][8];
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
USING_NS_CC;
int CurrentLev = 1;
int MaxLev = 0;


char fileMap[20];
using namespace  std;


bool loadMap()//加载地图
{
	char fileName[300];
	ssize_t size = 0;
	sprintf(fileName, "%d.lib", CurrentLev);
	unsigned char*str = FileUtils::getInstance()->getFileData(fileName, "r", &size);
	if (size <= 0)return false;
		for (int i = 1; i < 12; i++)
		{
			for (int y = 1; y < 7; )
			{
				if (*str == '.')return true;

				if (*str>'9' || *str < '0')
				{
					str++;
					continue;
				}
				data[i][y] = *str - '0';

				str ++;
				y++;
			}
		}	
	return true;
}

class searchAlg
{
public:

	int search_0(Point2D pre, Point2D las, queue<Point2D> &tmp)
	{
		/*
		二维坐标0代表 空
		搜索0拐点
		return 0 代表未找到
		return N N代表路径数(两点差值)
		相邻返回1 隔一个返回2  以此类推
		*/
		int x_pre = pre.x;
		int y_pre = pre.y;
		int x_las = las.x;
		int y_las = las.y;


		//x变量
		if (y_pre == y_las)
		{
			int min = x_pre > x_las ? x_las : x_pre;
			int max = x_pre < x_las ? x_las : x_pre;

			tmp.push(Point2D(x_pre, y_pre));
			if (x_pre>x_las)
			{
				for (int x = max - 1; x > min; x--)
				{

					if (data[x][y_pre] == 0)
					{
						tmp.push(Point2D(x, y_pre));

					}
					else
					{
						return 0;
					}
				}

			}


			if (x_pre <= x_las) //等价
				//else
			{
				for (int x = min + 1; x < max; x++)
				{

					if (data[x][y_pre] == 0)
					{
						tmp.push(Point2D(x, y_pre));

					}
					else
					{
						return 0;
					}
				}

			}

			return (max - min); //代表队列多少个数据
		}






		///y变量
		if (x_pre == x_las)
		{

			int min = y_pre > y_las ? y_las : y_pre;
			int max = y_pre < y_las ? y_las : y_pre;

			tmp.push(Point2D(x_pre, y_pre));

			if (y_pre>y_las)
			{
				for (int y = max - 1; y > min; y--)
				{

					if (data[x_pre][y] == 0)
					{
						tmp.push(Point2D(x_pre, y));
					}
					else
					{
						return 0;
					}
				}
			}

			if (y_pre <= y_las)
			{
				for (int y = min + 1; y < max; y++)
				{

					if (data[x_pre][y] == 0)
					{
						tmp.push(Point2D(x_pre, y));
					}
					else
					{
						return 0;
					}
				}

			}

			return (max - min); //代表队列多少个数据

		}




		return 0;
	}



	int search_1(Point2D pre, Point2D las, queue<Point2D> &tmp)
		//1个拐点
	{
		if (data[las.x][pre.y] == 0)//右下
		{
			if (search_0(pre, Point2D(las.x, pre.y), tmp) != 0)
			{
				if (search_0(Point2D(las.x, pre.y), las, tmp) != 0)
				{
					return  tmp.size();
				}
			}
		}

		for (; !tmp.empty();)//清空
		{
			tmp.pop();
		}


		if (data[pre.x][las.y] == 0)//左上
		{
			if (search_0(pre, Point2D(pre.x, las.y), tmp) != 0)
			{
				if (search_0(Point2D(pre.x, las.y), las, tmp) != 0)
				{

					return tmp.size();
				}
			}
		}

		return 0;
	}



	int search_2(Point2D pre, Point2D las, queue<Point2D> &tmp)
	{//2拐点

		//凹型y+
		for (int i = 0; i < y; i++)
		{

			for (; !tmp.empty();)//清空
			{
				tmp.pop();
			}


			if (data[las.x][las.y + i] == 0)//凹型
			{
				if (search_1(pre, Point2D(las.x, las.y + i), tmp) != 0)
				{
					if (search_0(Point2D(las.x, las.y + i), las, tmp) != 0)
					{

						return tmp.size();
					}
				}
			}
		}




		for (; tmp.empty() == false;)
		{
			tmp.pop();
		}



		//凹型y-
		for (int i = 0; i < y; i++)
		{

			for (; !tmp.empty();)//清空
			{
				tmp.pop();
			}


			if (data[las.x][las.y - i] == 0)//凹型
			{
				if (search_1(pre, Point2D(las.x, las.y - i), tmp) != 0)
				{
					if (search_0(Point2D(las.x, las.y - i), las, tmp) != 0)
					{

						return tmp.size();
					}
				}
			}
		}




		for (; tmp.empty() == false;)
		{
			tmp.pop();
		}






		//凹型x+
		for (int i = 0; i < x; i++)
		{

			for (; !tmp.empty();)//清空
			{
				tmp.pop();
			}


			if (data[las.x + i][las.y] == 0)//凹型
			{
				if (search_1(pre, Point2D(las.x + i, las.y), tmp) != 0)
				{
					if (search_0(Point2D(las.x + i, las.y), las, tmp) != 0)
					{

						return tmp.size();
					}
				}
			}
		}



		for (; tmp.empty() == false;)
		{
			tmp.pop();
		}



		//凹型x-
		for (int i = 0; i < x; i++)
		{

			for (; !tmp.empty();)//清空
			{
				tmp.pop();
			}


			if (data[las.x - i][las.y] == 0)//凹型
			{
				if (search_1(pre, Point2D(las.x - i, las.y), tmp) != 0)
				{
					if (search_0(Point2D(las.x - i, las.y), las, tmp) != 0)
					{

						return tmp.size();
					}
				}
			}
		}







		return 0;

	}


	int x;
	int y;

	searchAlg(int l, int w) :y(l), x(w)
	{

	}
};






















searchAlg* judge = new searchAlg(13, 8);




Scene* logo::createScene()
{
	auto scene = Scene::create();
	auto layer = logo::create();
	scene->addChild(layer);
	return scene;
}


bool logo::init()
{
	Layer::init();

	auto bg = Sprite::create("logo1.png");
	bg->setPosition(1136 / 2, 640 / 2);
	this->addChild(bg);

	this->runAction(Sequence::create(DelayTime::create(4), CallFunc::create([=]{
		SimpleAudioEngine::getInstance()->playBackgroundMusic("class.mp3", true);

		Director::getInstance()->replaceScene(HelloWorld::createScene());


	}), nullptr));

	return true;
}






Scene* HelloWorld::createScene()
{

	auto scene = Scene::create();
	auto layer = HelloWorld::create();
	scene->addChild(layer);
	return scene;
}

bool HelloWorld::init()
{
	Layer::init();

	auto ss = Sprite::create("h.png");
	ss->setPosition(1136 / 2, 640 / 2);
	this->addChild(ss);



	sss = Sprite::create("title.png");

	this->addChild(sss);


	menu_play = MenuItemImage::create("play.png", "play.png", "play.png", this, menu_selector(HelloWorld::menuCloseCallback));

	auto men = Menu::create(menu_play, nullptr);
	men->setPosition(0, 0);
	this->addChild(men);


	menu_play->setPosition(1136 / 2, -200);
	sss->setPosition(1136 / 2, 640 + 200);


	menu_play->runAction(MoveTo::create(0.2, Vec2(1136 / 2, 640 / 2 - 100)));

	sss->runAction(MoveTo::create(0.2, Vec2(1136 / 2, 640 / 2 + 120)));

	auto menu_back2 = MenuItemImage::create("back.png", "back.png", "back.png", [=](Ref*p)
	{
		exit(0);
	});
	menu_back2->setPosition(1136 / 2 - 530, 640 / 2+280);
	menu_back2->setScale(1.5);
	auto men2 = Menu::create(menu_back2, nullptr);
	men2->setPosition(0, 0);
	this->addChild(men2);




	return true;
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
	menu_play->runAction(MoveTo::create(0.2, Vec2(1136 / 2, -200)));

	sss->runAction(MoveTo::create(0.1, Vec2(1136 / 2, 640 + 200)));

	this->runAction(Sequence::create(DelayTime::create(0.2), CallFunc::create([=]{
		Director::getInstance()->replaceScene(selectScene::createScene());

	}), nullptr));

}







Scene* selectScene::createScene()
{

	auto scene = Scene::create();
	auto layer = selectScene::create();
	scene->addChild(layer);
	return scene;
}

bool selectScene::init()
{
	Layer::init();


	if (UserDefault::getInstance()->getIntegerForKey("max") < 0 || UserDefault::getInstance()->getIntegerForKey("max")>=77)
	{
		UserDefault::getInstance()->setIntegerForKey("max", 0);

	}
	else
	{
		MaxLev = UserDefault::getInstance()->getIntegerForKey("max");
	}

	auto ss = Sprite::create("h.png");
	ss->setPosition(1136 / 2, 640 / 2);
	this->addChild(ss);

	auto s1s = Sprite::create("dark.png");
	s1s->setPosition(1136 / 2, 640 / 2 - 50);
	this->addChild(s1s);
	s1s->setOpacity(90);
	s1s->setScale(1.6);

	auto menu_back = MenuItemImage::create("back.png", "back.png", "back.png", this, menu_selector(selectScene::call_back));
	menu_back->setPosition(1136 / 2 - 530, 640 / 2 + 280);
	menu_back->setScale(1.4);
	auto men = Menu::create(menu_back, nullptr);
	men->setPosition(0, 0);
	this->addChild(men);





	char str[20];
	int xx = 1;
	for (int i = 0; i < 7; i++)
	{
		for (int ii = 0; ii < 11; ii++, xx++)
		{

			sprintf(str, "%d", xx);
			auto mm = MenuItemFont::create(str, [=](Ref*p){
				CurrentLev = xx;
				call_back1();
			});
			mm->setPosition(80 * ii + 150, 530 - 80 * i);

			mm->setScale(1.7);
			if (xx > (MaxLev+1))
			{
				mm->setEnabled(false);
				mm->setColor(Color3B(0,0,0));
			}
			auto men = Menu::create(mm, nullptr);
			men->setPosition(0, 0);
			this->addChild(men);
		}
	}


	auto guan = Sprite::create("guan.png");
	guan->setPosition(1136 / 2, 640 / 2 + 290);
	this->addChild(guan);
	guan->setScale(0.6);



	return true;
}

void selectScene::menuCloseCallback(Ref* pSender)
{


	this->runAction(Sequence::create(DelayTime::create(0.2), CallFunc::create([=]{
		Director::getInstance()->replaceScene(TransitionFade::create(0.6, gameScene::createScene()));

	}), nullptr));

}






void selectScene::call_back(Ref* pSender)
{
	Director::getInstance()->replaceScene(HelloWorld::createScene());
}




void selectScene::call_back1()
{
	sprintf(fileMap, "%d.txt", CurrentLev);
	Director::getInstance()->replaceScene(gameScene::createScene());

}









Scene* gameScene::createScene()
{

	auto scene = Scene::create();
	auto layer = gameScene::create();
	scene->addChild(layer);
	return scene;
}

bool gameScene::init()
{
	Layer::init();
	auto bg = Sprite::create("bg.png");
	this->addChild(bg);
	bg->setPosition(1136 / 2, 640 / 2);


	for (int i = 0; i < 13; i++)
	{
		for (int y = 0; y < 8; y++)
		{
			data[i][y] = 0;
		}
	}

	loadMap();//加载地图
	log(".....%d......", CurrentLev);

	for (int x = 0; x < 13; x++)
	{

		log("%d %d %d %d %d %d %d %d", data[x][0], data[x][1], data[x][2], data[x][3],
			data[x][4], data[x][5], data[x][6], data[x][7]);

	}





	char ss[20];
	//初始化图片
	for (int i = 1; i < 12; i++)
	{
		for (int y = 1; y < 7; y++)
		{
			if (data[i][y] == 0)continue;
			sprintf(ss, "%d.png", data[i][y]);
			sprite[i][y] = Sprite::create(ss);
			this->addChild(sprite[i][y]);
			sprite[i][y]->setPosition(85 * (i - 1) + 143.0, 85 * (y - 1) + 45);
		}
	}


	initTouch();


	time_ = Sprite::create("time.png");
	time_->setPosition(536 / 2, 640 / 2 + 310);
	this->addChild(time_);
	time_->setScaleY(2.0);




	auto menu_back = MenuItemImage::create("back.png", "back.png", "back.png", this, menu_selector(gameScene::call_back));
	menu_back->setPosition(1136 / 2 -520, 640 / 2 + 250);
	menu_back->setScale(1.4);
	auto men = Menu::create(menu_back, nullptr);
	men->setPosition(0, 0);
	this->addChild(men);
	char str[20];
	sprintf(str, "Level : %d", CurrentLev);

	auto lab = LabelTTF::create(str, "GeezaPro", 50);
	this->addChild(lab);
	lab->setPosition(1136 / 2, 640 / 2 + 260);





	scheduleUpdate();
	return true;
}

void gameScene::menuCloseCallback(Ref* pSender)
{
	exit(0);
}


void gameScene::call_back(Ref* pSender)
{


	Director::getInstance()->replaceScene(selectScene::createScene());
}



void gameScene::runMatch(int x, int y)
{

	float maxTime = tmp.size()*0.07;

	listener->setEnabled(false);

	auto ss = ParticleFire::create();
	this->addChild(ss);

	ss->setDuration(maxTime);
	ss->setLife(maxTime);

	ss->setTotalParticles(555);
	ss->setScale(0.25);

	ss->setPosition(sprite[x][y]->getPosition());

	ss->setAutoRemoveOnFinish(true);

	auto arry = PointArray::create(20);
	while (tmp.empty() == false)
	{
		arry->addControlPoint(Point(85 * (tmp.front().x - 1) + 143, (tmp.front().y - 1) * 85 + 45));
		tmp.pop();
	}
	arry->addControlPoint(Point(85 * (las.x - 1) + 143, (las.y - 1) * 85 + 45));

	ss->runAction(Sequence::create(
		CatmullRomTo::create(maxTime, arry),
		CallFunc::create([=]{

		sprite[x][y]->setVisible(false);
		data[x][y] = 0;
		sprite[las.x][las.y]->setVisible(false);
		data[las.x][las.y] = 0;
		listener->setEnabled(true);
		if (isOver() == true)
		{
			if (CurrentLev >= MaxLev)
			{
				MaxLev = CurrentLev;
				UserDefault::getInstance()->setIntegerForKey("max", MaxLev);
			}
			switchLev(1, true);
			unscheduleUpdate();

		}


	}), nullptr));



}


void gameScene::initTouch()
{

	listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = [=](Touch*touch, Event*event)
	{

		auto point = touch->getLocation();


		//越界
		if (point.x <= 103 || point.x >= 1031)
		{
			return false;
		}

		if (point.y <= 5 || point.y >= 510)
		{
			return false;
		}


		int x = (point.x - 143.0 / 2.0) / 85.0 + 1;
		int y = (point.y - 35.0 / 2.0) / 85.0 + 1;

		if (x >= 12)x = 11;

		//空白
		if (data[x][y] == 0)return false;

		//选中
		bool tag = false;
		for (int i = 1; i < 12; i++)
		{
			for (int y = 1; y < 7; y++)
			{
				if (data[i][y] == 0)continue;
				if (sprite[i][y]->getTag() == 5)
				{
					sprite[i][y]->setScale(1);
					sprite[i][y]->setTag(0);
					las.x = i;
					las.y = y;
					tag = true;
				}
			}
		}


		log("%d,%d", x, y);
		sprite[x][y]->setScale(1.3);
		sprite[x][y]->setTag(5);


		if (tag == false)return false;

		//相同的点
		if (las.x == x&&las.y == y)return false;

		//首末图片必须相等
		if (data[x][y] != data[las.x][las.y])return false;

		if (
			(judge->search_0(Point2D(x, y), las, tmp) != 0) ||
			(judge->search_1(Point2D(x, y), las, tmp) != 0)
			|| (judge->search_2(Point2D(x, y), las, tmp) != 0)
			)
		{
			//消除
			runMatch(x, y);
		}

		for (; tmp.empty() == false;)//清空队列
		{
			tmp.pop();
		}
		return true;
	};

	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);




}



bool gameScene::isOver()
{
	for (int i = 1; i < 12; i++)
	{
		for (int y = 1; y < 7; y++)
		{
			if (data[i][y] != 0)return false;
		}
	}
	return true;
}



void gameScene::switchLev(int lev, bool isWin)
{
	overLayer = Layer::create();
	this->addChild(overLayer);


	//透明背景
	auto menu_back = MenuItemImage::create("dark.png", "dark.png", "dark.png", this, menu_selector(gameScene::call));
	menu_back->setPosition(1136 / 2, 640 / 2);
	menu_back->setScale(5);
	menu_back->setOpacity(90);
	auto men = Menu::create(menu_back, nullptr);
	men->setPosition(0, 0);
	overLayer->addChild(men);

	//对话框背景
	auto dia = Sprite::create("dia.png");
	overLayer->addChild(dia);
	dia->setPosition(1136 / 2, 640 / 2);





	//下一关
	if (isWin == true)
	{

		//返回列表
		auto mm1 = MenuItemImage::create("list.png", "list.png", "list.png", [=](Ref*p){
			Director::getInstance()->replaceScene(selectScene::createScene()); }
		);
		mm1->setPosition(1136 / 2 - 220, 640 / 2 - 130);

		auto men1 = Menu::create(mm1, nullptr);
		men1->setPosition(0, 0);
		overLayer->addChild(men1);



		//重新开始
		auto mm11 = MenuItemImage::create("re.png", "re.png", "re.png", [=](Ref*p){
			Director::getInstance()->replaceScene(gameScene::createScene());


		}
		);
		mm11->setPosition(1136 / 2, 640 / 2 - 130);

		auto men11 = Menu::create(mm11, nullptr);
		men11->setPosition(0, 0);
		overLayer->addChild(men11);


		auto mm1111 = MenuItemImage::create("ne.png", "ne.png", "ne.png", [=](Ref*p){
			CurrentLev++;
			Director::getInstance()->replaceScene(gameScene::createScene());
		}
		);
		mm1111->setPosition(1136 / 2 + 220, 640 / 2 - 130);

		auto men112 = Menu::create(mm1111, nullptr);
		men112->setPosition(0, 0);
		overLayer->addChild(men112);

		auto title = Sprite::create("win.png");
		title->setPosition(1136 / 2, 640 / 2 + 90);
		overLayer->addChild(title);
		title->setScale(1.5);

	}
	else
	{
		//返回列表
		auto mm1 = MenuItemImage::create("list.png", "list.png", "list.png", [=](Ref*p){
			Director::getInstance()->replaceScene(selectScene::createScene()); }
		);
		mm1->setPosition(1136 / 2 - 110, 640 / 2 - 130);

		auto men1 = Menu::create(mm1, nullptr);
		men1->setPosition(0, 0);
		overLayer->addChild(men1);



		//重新开始
		auto mm111 = MenuItemImage::create("re.png", "re.png", "re.png", [=](Ref*p){
			Director::getInstance()->replaceScene(gameScene::createScene());


		}
		);
		mm111->setPosition(1136 / 2 + 110, 640 / 2 - 130);

		auto men111 = Menu::create(mm111, nullptr);
		men111->setPosition(0, 0);
		overLayer->addChild(men111);

		auto title = Sprite::create("false.png");
		title->setPosition(1136 / 2, 640 / 2 + 90);
		overLayer->addChild(title);
		title->setScale(1.5);

	}

}


